angular.module('U9ImHd.services')

.factory('AppManager', ['$q', '$http', '$cordovaZip', '$cordovaFile', 'Connect', 'Http', 'Config', 'Help', 'imanDialog', 'APPCONSTANTS',
    function($q, $http, $cordovaZip, $cordovaFile, Connect, Http, Config, Help, imanDialog, APPCONSTANTS) {
        var amDefer = $q.defer(),
            _appList = [],
            _apps = [],
            o = {
                loaded: amDefer.promise
            };

        o.getApps = function () {
            var results = [];
            angular.forEach(angular.copy(_appList), function (app) {
                var temp = queryApp(app.AppID);
                if (temp) {
                    temp.DisplayImage = Help.getFullPath(temp.DisplayImage, temp.AppID);
                    if (temp.MouseDownImage) {
                        temp.MouseDownImage = Help.getFullPath(temp.MouseDownImage, temp.AppID);
                    }
                    results.push(temp);
                }
            });
            return results;
        };
        o.installApps = function () {
            var defer = $q.defer();

            getAppList().then(function () {
                return batchInstall();
            }).then(function () {
                defer.resolve();
            }, function (err) {
                defer.resolve();
            });

            return defer.promise;
        };
        o.checkUpdate = function (hasTip) {
            var defer = $q.defer();

            Http.post({
                url: APPCONSTANTS.getAppURL,
                data: {
                    AppId: APPCONSTANTS.appID
                }
            }).then(function (data) {
                if (window.cordova && cordova.plugins.Install && data.Version > APPCONSTANTS.appVersion) {
                    imanDialog.alert('有新的更新可用，请进行更新。', '版本更新').then(function () {
                        imanDialog.showLoading();
                        return downloadMainApp(data.FileName);
                    }).then(function () {
                        imanDialog.hideLoading();
                        installMainApp();
                        defer.resolve();
                    }, function () {
                        defer.resolve();
                    });
                } else {
                    if (hasTip) {
                        imanDialog.toastBottom('您的应用是最新版本');
                    }
                    defer.resolve();
                }
            }, function () {
                defer.resolve();
            });

            return defer.promise;
        };

        init();

        return o;

        function init () {
            Connect.loaded.finally(function () {
                _apps = Config.get('apps', []);
                o.checkUpdate();
                amDefer.resolve();
            });
        }

        function installMainApp () {
            cordova.plugins.Install.install('/' + APPCONSTANTS.appID + '/' + APPCONSTANTS.appID + '.apk', function (cancelled) {
                if (cancelled) {
                    imanDialog.alert('请安装更新再进行其他操作。', '安装更新').then(function () {
                        installMainApp();
                    });
                }
            }, function () {
                imanDialog.toastBottom('安装更新失败');
            });
        }

        function downloadMainApp (fileName) {
            var defer = $q.defer();

            if (!window.cordova) {
                defer.resolve();
            } else {
                $http({
                    method: 'POST',
                    url: 'http://' + Connect.getServeParameter('GatewayAddress') + APPCONSTANTS.downloadAppURL,
                    data: {
                        FileName: fileName
                    },
                    timeout: 30000,
                    responseType: 'arraybuffer'
                }).then(function (result) {
                    var blob = new Blob([result.data], { type: "application/octet-binary" });
                    return $cordovaFile.writeFile(Help.getConfigDir(), APPCONSTANTS.appID + '.apk', blob, true);
                }).then(function () {
                    defer.resolve();
                }).catch(function () {
                    defer.reject();
                });
            }

            return defer.promise;
        }

        function getAppList () {
            var defer = $q.defer();

            Http.post({
                url: APPCONSTANTS.getAppsURL,
                data: {
                    Type: 0
                }
            }).then(function (appList) {
                _appList = appList;
                defer.resolve(appList);
            }, function () {
                defer.reject();
            });

            return defer.promise;
        }

        function queryApp (appID) {
            var len = _apps.length,
                i = 0;
            for (; i < len; i++) {
                if (_apps[i].AppID === appID) {
                    break;
                }
            }
            if (i < len) {
                return angular.copy(_apps[i]);
            } else {
                return null;
            }
        }

        function batchInstall () {
            var defer = $q.defer();

            var batches = [], 
                failedAppList = [];
            for (var i = 0, len = _appList.length; i < len; i++) {
                var installed = false;
                for (var j = 0, l = _apps.length; j < l; j++) {
                    if (_appList[i].AppID === _apps[j].AppID) {
                        if (_appList[i].Version > _apps[j].Version) {
                            batches.push(updateApp(_appList[i], failedAppList, true));
                        }
                        installed = true;
                        break;
                    }
                }
                if (!installed) {
                    batches.push(installApp(_appList[i], failedAppList, true));
                }
            }
            if (batches.length === 0) {
                defer.resolve();
            } else {
                $q.all(batches).then(function () {
                    return Config.set('apps', _apps);
                }).then(function () {
                    if (failedAppList.length > 0) {
                        imanDialog.alert(failedAppList.join('、'), '下列应用下载安装异常');
                    }
                    defer.resolve();
                }).catch(function () {
                    defer.resolve();
                });
            }

            return defer.promise;
        }

        function updateApp (app, failedAppList, notWriteFile) {
            var defer = $q.defer();

            var index = checkInstalled(app.AppID);
            if (!window.cordova || index === -1) {
                defer.resolve();
            } else {
                removeApp(app.AppID).then(function () {
                    return downloadApp(app.AppID, app.FileName);
                }).then(function () {
                    return $cordovaFile.readAsText(Help.getAppsDir() + app.AppID, APPCONSTANTS.appConfigFileName);
                }).then(function (data) {
                    angular.extend(_apps[index], angular.fromJson(data));
                    if (notWriteFile) {
                        return $q.resolve();
                    } else {
                        return Config.set('apps', _apps);
                    }
                }).then(function () {
                    defer.resolve();
                }).catch(function () {
                    if (failedAppList) {
                        failedAppList.push(app.Name);
                    }
                    defer.resolve();
                });
            }      

            return defer.promise;
        }

        function installApp (app, failedAppList, notWriteFile) {
            var defer = $q.defer();

            if (!window.cordova) {
                defer.resolve();
            } else {
                downloadApp(app.AppID, app.FileName).then(function () {
                    return $cordovaFile.readAsText(Help.getAppsDir() + app.AppID, APPCONSTANTS.appConfigFileName);
                }).then(function (data) {
                    _apps.push(angular.fromJson(data));
                    if (notWriteFile) {
                        return $q.resolve();
                    } else {
                        return Config.set('apps', _apps);
                    }
                }).then(function () {
                    defer.resolve();
                }).catch(function () {
                    if (failedAppList) {
                        failedAppList.push(app.Name);
                    }
                    defer.resolve();
                });
            }

            return defer.promise;
        }

        function checkInstalled (appID) {
            var len = _apps.length;
            for (var i = 0; i < len; i++) {
                if (_apps[i].AppID === appID) {
                    break;
                }
            }
            if (i === len) {
                return -1;
            } else {
                return i; 
            }
        }

        function downloadApp (appID, fileName) {
            var defer = $q.defer();

            if (!window.cordova) {
                defer.resolve();
            } else {
                $http({
                    method: 'POST',
                    url: 'http://' + Connect.getServeParameter('GatewayAddress') + APPCONSTANTS.downloadAppURL,
                    data: {
                        FileName: fileName
                    },
                    responseType: 'arraybuffer'
                }).then(function (result) {
                    var blob = new Blob([result.data], { type: "application/octet-binary" });
                    return $cordovaFile.writeFile(Help.getConfigDir(), appID + '.zip', blob, true);
                }).then(function () {
                    var fileURL = Help.getConfigDir() + appID + '.zip';
                    return $cordovaZip.unzip(fileURL, Help.getAppsDir());
                }).then(function () {
                    return $cordovaFile.removeFile(Help.getConfigDir(), appID + '.zip');
                }).then(function () {
                    defer.resolve();
                }).catch(function () {
                    defer.reject();
                });
            }

            return defer.promise;
        }

        function removeApp (appID) {
            var defer = $q.defer();

            if (window.cordova) {
                $cordovaFile.removeRecursively(Help.getAppsDir(), appID).then(function () {
                    defer.resolve();
                }, function (error) {
                    defer.reject();
                });
            } else {
                defer.reject();
            }

            return defer.promise;
        }
    }
]);